package com.lncg.util;

import com.lncg.entity.DeviceReceiveData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

/**
 * 简化的协议解析器 - 解析92字节数据包
 */
@Component
public class LncgProtocolParser {
    
    private static final Logger logger = LoggerFactory.getLogger(LncgProtocolParser.class);
    
    
    /**
     * 解析92字节数据包
     * @param data 接收到的字节数组
     * @return 解析后的设备数据对象
     */
    public DeviceReceiveData parseProtocol(byte[] data) {
        if (data.length != 92) {
            throw new IllegalArgumentException("数据包长度必须为92字节，实际长度：" + data.length);
        }
        
        DeviceReceiveData deviceData = new DeviceReceiveData();
        ByteBuffer buffer = ByteBuffer.wrap(data);
        
        // 开始解析92字节数据包
        
        try {
            // 1. 前导符：[1-2] 共2字节，0x43 0x47
            byte[] prefix = new byte[2];
            buffer.get(prefix);
            if (prefix[0] != 0x43 || prefix[1] != 0x47) {
                throw new IllegalArgumentException("前导符错误，期望：0x43 0x47，实际：" + 
                    String.format("0x%02X 0x%02X", prefix[0] & 0xFF, prefix[1] & 0xFF));
            }
            
            // 2. 指令编号：[3-12] 共10字节
            byte[] instructionIdBytes = new byte[10];
            buffer.get(instructionIdBytes);
            deviceData.setInstructionId(bytesToHex(instructionIdBytes));
            
            // 3. 指令类型：[13-13] 共1字节
            int instructionType = buffer.get() & 0xFF;
            deviceData.setInstructionType(instructionType);
            
            // 4. IMEI：[14-29] 共16字节
            byte[] imeiBytes = new byte[16];
            buffer.get(imeiBytes);
            String imei = new String(imeiBytes, StandardCharsets.US_ASCII);
            imei = imei.replaceAll("\0", "").trim();
            deviceData.setImei(imei);
            
            // 5. 表号：[30-45] 共16字节
            byte[] meterCodeBytes = new byte[16];
            buffer.get(meterCodeBytes);
            String meterCode = new String(meterCodeBytes, StandardCharsets.US_ASCII);
            deviceData.setMeterCode(meterCode);
            
            // 6. SIM卡号：[46-65] 共20字节
            byte[] simBytes = new byte[20];
            buffer.get(simBytes);
            String sim = new String(simBytes, StandardCharsets.US_ASCII);
            deviceData.setSim(sim);
            
            // 7. 厂商标识：[66-67] 共2字节
            byte[] vendorBytes = new byte[2];
            buffer.get(vendorBytes);
            String vendorCode = new String(vendorBytes, StandardCharsets.US_ASCII);
            deviceData.setVendorCode(vendorCode);
            
            // 8. 通信方式：[68-68] 共1字节
            int commMethod = buffer.get() & 0xFF;
            deviceData.setCommMethod(commMethod);
            
            // 9. 计量单位：[69-69] 共1字节
            int unitCode = buffer.get() & 0xFF;
            deviceData.setUnitCode(unitCode);
            
            // 10. 表具类型：[70-70] 共1字节
            int deviceType = buffer.get() & 0xFF;
            deviceData.setDeviceType(deviceType);
            
            // 11. 表具口径：[71-71] 共1字节
            int caliberCode = buffer.get() & 0xFF;
            deviceData.setCaliberCode(caliberCode);
            
            // 12. 协议版本号：[72-72] 共1字节
            int protocolVer = buffer.get() & 0xFF;
            deviceData.setProtocolVer(protocolVer);
            
            // 13. 信号强度：[73-73] 共1字节
            int signalLevel = buffer.get() & 0xFF;
            deviceData.setSignalLevel(signalLevel);
            
            // 14. 上线状态：[74-74] 共1字节
            int onlineState = buffer.get() & 0xFF;
            deviceData.setOnlineState(onlineState);
            
            // 15. 电池电压：[75-78] 共4字节
            byte[] batteryBytes = new byte[4];
            buffer.get(batteryBytes);
            String batteryVoltage = new String(batteryBytes, StandardCharsets.US_ASCII);
            deviceData.setBatteryVoltage(batteryVoltage);
            
            // 16. 正累计数据：[79-82] 共4字节
            byte[] positiveBytes = new byte[4];
            buffer.get(positiveBytes);
            int positiveValue = bytesToInt(positiveBytes);
            deviceData.setPositiveData(String.valueOf(positiveValue));
            
            // 17. 负累计数据：[83-86] 共4字节
            byte[] negativeBytes = new byte[4];
            buffer.get(negativeBytes);
            int negativeValue = bytesToInt(negativeBytes);
            deviceData.setNegativeData(String.valueOf(negativeValue));
            
            // 18. 上线间隔：[87-87] 共1字节
            int onlineIntervalValue = buffer.get() & 0xFF;
            String onlineInterval = String.format("%02X", onlineIntervalValue);
            deviceData.setOnlineInterval(onlineInterval);
            
            // 19. 重发次数：[88-88] 共1字节
            int retryCount = buffer.get() & 0xFF;
            deviceData.setRetryCount(retryCount);
            
            // 20. 表具状态：[89-89] 共1字节
            int meterStatus = buffer.get() & 0xFF;
            deviceData.setMeterStatus(meterStatus);
            
            // 21. CRC16：[90-91] 共2字节
            byte[] crcBytes = new byte[2];
            buffer.get(crcBytes);
            String crc16 = bytesToHex(crcBytes);
            deviceData.setCrc16(crc16);
            
            // 22. 结束符：[92-92] 共1字节，0x16
            byte endFlag = buffer.get();
            if (endFlag != 0x16) {
                throw new IllegalArgumentException("结束符错误，期望：0x16，实际：0x" + 
                    String.format("%02X", endFlag & 0xFF));
            }
            
            // 设置原始报文
            deviceData.setRawFrame(bytesToHex(data));
            
            // 协议解析完成
            
        } catch (Exception e) {
            logger.error("协议解析失败: {}", e.getMessage());
            throw new RuntimeException("协议解析失败：" + e.getMessage(), e);
        }
        
        return deviceData;
    }
    
    /**
     * 将字节数组转换为十六进制字符串
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
    
    /**
     * 将4字节数组转换为int
     * @param bytes 4字节数组
     * @return int值
     */
    public static int bytesToInt(byte[] bytes) {
        if (bytes.length != 4) {
            throw new IllegalArgumentException("字节数组长度必须为4");
        }
        return ByteBuffer.wrap(bytes).getInt();
    }
    
    /**
     * 计算CRC16 ModBus校验码
     * @param data 需要校验的字节数组
     * @return CRC16校验码
     */
    public static short calculateCrc16(byte[] data) {
        int crc = 0xFFFF; // 初始值
        for (byte b : data) {
            crc ^= (b & 0xFF); // 异或
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x0001) != 0) {
                    crc >>= 1;
                    crc ^= 0xA001; // 多项式
                } else {
                    crc >>= 1;
                }
            }
        }
        return (short) crc;
    }
    
    /**
     * 验证CRC16校验码
     * @param data 需要校验的字节数组
     * @param receivedCrc 接收到的CRC校验码（小端序：低字节在前）
     * @return 校验是否通过
     */
    public static boolean verifyCrc16(byte[] data, byte[] receivedCrc) {
        short calculatedCrc = calculateCrc16(data);
        // ModBus CRC16使用小端序：低字节在前，高字节在后
        // receivedCrc[0]是低字节，receivedCrc[1]是高字节
        short receivedCrcValue = (short) ((receivedCrc[1] & 0xFF) << 8 | (receivedCrc[0] & 0xFF));
        return calculatedCrc == receivedCrcValue;
    }
    
}